共计 1891 个字符,预计需要花费 5 分钟才能阅读完成。
引入
栈区 / 堆区
- 栈区 : 存放的是变量名与变量值的内存地址 映射关系
- 堆区 : 存放的是值 真正的位置
一. 名称空间
1. 什么是名称空间
- 存放名字与值绑定关系的地方
- 名称空间是一个虚拟的概念, 栈区才真实存在
2. 为什么要有名称空间
- 有了名称空间后就可以在内存的栈区存放相同的名字, 并且不会冲突
3. 名称空间是否有包含关系?
- 名称空间本质之间是没有包含关系的, 并且相互独立
二. 名称空间的分类(三类)
1. 内置名称空间
- 存放内置的名字
- 周期 : 在解释器启动时就产生,解释器关闭则失效
🎅例如我们常用的内置函数
print
len
input
2. 全局名称空间
- 存放的是顶级的名字 (文件级别的名字)
- 周期 : 在执行文件时生效,文件运行完毕或文件执行期间被删除则失效
x = 1 #全局名称空间
def foo(): #全局名称空间
y = 2
🎅注意,"if" 下面的定义的变量名都是全局的
if 1 > 0
z = 3 #全局
if 3 > 0:
p = 555 #全局
3. 局部名称空间
- 存放函数内定义的名字
- 周期 : 在函数调用时临时生效, 函数结束时则失效
def f()
x = 222 #局部名称空间
f() #函数调用结束失效
4. 名称空间的加载顺序
'内置名称空间'----->'全局名称空间'----->'局部名称空间'
5. 名称空间的查找优先级
'局部名称空间'----->'全局名称空间'----->'内置名称空间'
6. 名称空间的销毁顺序
'局部名称空间'----->'全局名称空间'----->'内置名称空间'
7. 名称空间总结与注意事项
- 重要概念:名称空间的嵌套关系是在 函数定义阶段 (检测语法) 时确定的,与函数调用的位置无关,与函数 定义位置有关
-
三种名称空间必须要有的是 : 内置 名称空间, 全局 名称空间
-
查找优先级示例
🎅从 "f2" 局部开始找
x = 3
def f1():
x = 2
def f2():
x =1
print(x)
f2()
f1() # 1
🎅将 "f2" 局部的删除, 就往上一层找, 找到 "f1"
x = 3
def f1():
x = 2
def f2():
print(x)
f2()
f1() # 2
🎅再将 "f1" 里面的删除, 于是找到了全局
x = 3
def f1():
def f2():
print(x)
f2()
f1() # 3
- 函数的嵌套定义示例
🎅在定义 "f2" 的之后, 有定义了同一级别的 "len", 所以当打开函数 "f2" 运行的时候, 本着优先级查找就先找到了 "222"
len = 111
def f1():
def f2():
print(len) # 222
len = 222
f2()
f1() # 222
三. 作用域
1. 什么是作用域
- 作用域就是根据名称空间的范围和特点进行了归类
- 查看作用域 : globals(), locals()
2. 全局作用域
- 包含 : 内置名称空间, 全局名称空间
- 特点 : 全局存活, 全局有效
3. 局部作用域
- 包含 : 局部名称空间
- 特点 : 临时存活, 局部有效
4.L E G B
- LEGB 代表名字查找顺序 : L--->E--->G--->B
- locals : 是函数内的名字空间, 包括局部变量和形参
- enclosing : 外部嵌套的名称空间(闭包中常见面)
- globals : 全局变量, 函数定义所在模块的名字空间
- builtins : 内置模块的名字空间
四.global 与 nonlocal 关键字
1.global 关键字
- 使用方法 : global x 声明这个 x 是全局变量
- 针对的是不可变类型的值
🎅在全局空间定义一个变量 "x", 函数 "foo", 在函数内部修改 "x" 的值
x = 111
def foo():
x = 222
foo()
print(x) #111
#发现并无软用
🎅使用 "global" 关键字之后
x = 111
def foo():
global x # 声明下面的 "x" 属于全局
x = 222
foo()
print(x) #222
#发现成功了
2.nonlocal 关键字
- 使用方法 : nonlocal x , 声明外层函数的局部变量
- 修改该函数外层函数包含的变量名对应的值, 也是针对不可变类型
- 注意 : 只能在局部名称空间中查找, 先从外部嵌套的函数找, 没找到再往上找, 如果都没找到则报错
🎅不做任何处理, 此函数应该是打印 "f2" 函数下的 "x = 333"
x = 111
def f1():
x = 222
def f2():
x = 333
def f3():
x = 444
f3()
print(x) #333
f2()
f1() # 333
🎅使用 "nonlocal" 关键字
x = 111
def f1():
x = 222
def f2():
x = 333
def f3():
nonlocal x #将下面的 "x = 444" 变成了上一层的 "x" 的值
x = 444
f3()
print(x)
f2()
f1() # 444
🎅如果外层函数都没有 "x" 这个值, 报错
x = 111 #并不会去全局修改
def f1():
def f2():
def f3():
nonlocal x
x = 444
f3()
print(x)
f2()
f1() #报错
正文完